// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "UberViewer.h"
#include "UberViewerDoc.h"
#include "MainFrm.h"
//#include "gl\GL.h"    // Include the standard OpenGL headers
//#include "ifcengine.h"
#include "ModelManager.h"



#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CMDITabsDemoDoc

IMPLEMENT_DYNCREATE(CUberViewerDoc, CDocument)

BEGIN_MESSAGE_MAP(CUberViewerDoc, CDocument)
	ON_COMMAND(ID_Import, &CUberViewerDoc::OnImport)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMDITabsDemoDoc construction/destruction

CUberViewerDoc::CUberViewerDoc() : m_loc(GS_EPSG4326, 52.008, 4.461, 0.0, 0.0)
{
	TRACE("CUberViewerDoc::CUberViewerDoc");

//	m_pModelManager = ((CMainFrame*)AfxGetMainWnd())->GetModelManager();
//	m_pTextureManager = ((CMainFrame*)AfxGetMainWnd())->GetTextureManager();

	m_changedModels   = true;
	m_changedTextures = true;
	m_changedLocation = true;

	m_OSmap = NULL;
	m_ShowOSmap = true;
}


CUberViewerDoc::~CUberViewerDoc()
{
	TRACE("CUberViewerDoc::~CUberViewerDoc");

	std::list<InstantiatedModel*>::iterator it = m_instantiatedModels.begin();
	for (; it != m_instantiatedModels.end(); it++)
	{
		gModelManager.RemoveModel((*it)->pModel);
		delete (*it);
	}
}


BOOL CUberViewerDoc::OnNewDocument()
{
	TRACE("CUberViewerDoc::OnNewDocument");

	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

	return TRUE;
}



/////////////////////////////////////////////////////////////////////////////
// CMDITabsDemoDoc serialization


void CUberViewerDoc::Serialize(CArchive& ar)
{
	TRACE("CUberViewerDoc::Serialize");

	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		InstantiatedModel *instModel = new InstantiatedModel(GS_EPSG4326, 52.008, 4.461, 0.0, 0.0);

		instModel->pModel = gModelManager.AddModel(ar.m_strFileName);
		m_instantiatedModels.push_back(instModel);

		UpdateGeoLocation();
		((CMainFrame*)AfxGetMainWnd())->UpdateDocPanes(this);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CMDITabsDemoDoc diagnostics

#ifdef _DEBUG
void CUberViewerDoc::AssertValid() const
{
//	TRACE("CUberViewerDoc::AssertValid");

	CDocument::AssertValid();
}

void CUberViewerDoc::Dump(CDumpContext& dc) const
{
//	TRACE("CUberViewerDoc::Dump");

	CDocument::Dump(dc);
}
#endif //_DEBUG



/////////////////////////////////////////////////////////////////////////////
// CMDITabsDemoDoc commands



/*
void CUberViewerDoc::SetSelectionViaInstance(SIfc3DObject *instance)
{
	TRACE("C3DView::OnLButtonDblClk");

	SIfcDocument *doc = m_FirstDocument;
	while(doc)
	{
		SIfc3DObject *inst = doc->p3DObjects;
		while (inst)
		{
			if (inst == instance)
			{
				SetSelection(doc, inst);
				return;
			}
			inst = inst->next;
		}
		doc = doc->next;
	}
}

void CUberViewerDoc::SetSelection(SIfcDocument* doc, SIfc3DObject *instance)
{
	TRACE("CModellingData::SelectionChanged");
    static int      last_mtrl;

	// reset the material of the last selected object
	if (m_SelectedInstance)
		m_SelectedInstance->mtrl = last_mtrl;

	m_SelectedInstance = instance;
	m_SelectedDocument = doc;

	if (m_SelectedInstance)
	{
		last_mtrl = m_SelectedInstance->mtrl;
		m_SelectedInstance->mtrl = 0;
	}
}
*/

void CUberViewerDoc::OnImport()
{
	TRACE("CUberViewerDoc::OnImport");

    CFileDialog dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("3D Files |*.gml;*.ifc;*.ifcxml|Ifc Files (*.ifc)|*.ifc|IFCxml Files (*.ifcxml)|*.ifcxml|CityGML Files (*.gml)|*.gml|All Files (*.*)|*.*||"), NULL);

    if (dlgFile.DoModal() == IDOK)
    {     
        POSITION pos = dlgFile.GetStartPosition();
        
        while (pos != NULL)
        {
            CString name = dlgFile.GetNextPathName(pos);
			InstantiatedModel *modelInst = new InstantiatedModel(GS_EPSG4326, 52.008, 4.461, 0.0, 0.0);

/*			model->location.m_geoSystem = GS_EPSG4326;
			model->location.m_geoX = 52.008;
			model->location.m_geoY = 4.461;
			model->location.m_geoZ = 0.0;
			model->location.m_orientation = 0.0;
*/
			modelInst->pModel = gModelManager.AddModel(name);
			m_instantiatedModels.push_back(modelInst);
	    }
		UpdateGeoLocation();
		((CMainFrame*)AfxGetMainWnd())->UpdateDocPanes(this);
	}
}


void CUberViewerDoc::UpdateGeoLocation()
{
	TRACE("CUberViewerDoc::UpdateGeoLocation");

	bool first = true;

	std::list<InstantiatedModel*>::iterator it = m_instantiatedModels.begin();
	for ( ; it != m_instantiatedModels.end(); it++)
	{
		CModel *model = (*it)->pModel;
		double cos_or = cos((*it)->location.m_orientation),
			   sin_or = sin((*it)->location.m_orientation), tx, ty, x[2], y[2];

		x[0] = x[1] = model->m_maxBB.y * cos_or - model->m_maxBB.x * sin_or;
		y[0] = y[1] = model->m_maxBB.y * sin_or + model->m_maxBB.x * cos_or;  

		tx = model->m_minBB.y * cos_or - model->m_maxBB.x * sin_or;
		ty = model->m_minBB.y * sin_or + model->m_maxBB.x * cos_or;
		if		(tx < x[0]) x[0] = tx;
		else if (tx > x[1]) x[1] = tx;
		if		(ty < y[0]) y[0] = ty;
		else if (ty > y[1]) y[1] = ty;

		tx = model->m_minBB.y * cos_or - model->m_minBB.x * sin_or;
		ty = model->m_minBB.y * sin_or + model->m_minBB.x * cos_or;
		if		(tx < x[0]) x[0] = tx;
		else if (tx > x[1]) x[1] = tx;
		if		(ty < y[0]) y[0] = ty;
		else if (ty > y[1]) y[1] = ty;

		tx = model->m_maxBB.y * cos_or - model->m_minBB.x * sin_or;
		ty = model->m_maxBB.y * sin_or + model->m_minBB.x * cos_or;
		if		(tx < x[0]) x[0] = tx;
		else if (tx > x[1]) x[1] = tx;
		if		(ty < y[0]) y[0] = ty;
		else if (ty > y[1]) y[1] = ty;

		(*it)->location.ConvertDeltaToLatLon(2, x, y);
	
		for (int i = 0; i < 2; i++)
		{
			if (first)
			{
				m_minlat = x[0];
				m_minlon = y[0];
				m_maxlat = x[1];
				m_maxlon = y[1];
				first = false;
			}
			else
			{
				if (x[0] < m_minlat) m_minlat = x[0];
				if (x[1] > m_maxlat) m_maxlat = x[1];
				if (y[0] < m_minlon) m_minlon = y[0];
				if (y[1] > m_maxlon) m_maxlon = y[1];
			}
		}
	}

//	m_loc.m_geoSystem = GS_EPSG4326;
	m_loc.m_geoX = (m_minlat + m_maxlat) / 2;
	m_loc.m_geoY = (m_minlon + m_maxlon) / 2;

	for (it = m_instantiatedModels.begin(); it != m_instantiatedModels.end(); it++)
	{
		(*it)->location.SetOffset(&m_loc);
	}

	// Get new Openstreetmap underlayer
	char str[1000];
	sprintf(str, "http://tah.openstreetmap.org/MapOf/?lat=%.6lf&long=%.6lf&z=17&w=2000&h=2000&skip_attr=on&format=jpeg", m_loc.m_geoX, m_loc.m_geoY);

	if (m_OSmap == NULL)
		m_OSmap = gTextureManager.AddTexture(str);
	else
		gTextureManager.ModTexture(m_OSmap, str);

	AfxGetMainWnd()->Invalidate();	
}

